﻿#include "middlewindow.h"
#include "ui_middlewindow.h"
#include "middle.h"
#include "class_ip_rule.h"

middlewindow::middlewindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::middlewindow)
{
    ui->setupUi(this);
    ui->pushButton_2->setEnabled(false);
}

middlewindow::~middlewindow()
{
    delete ui;
}


Cappackets cp;
Sendv sv;

void Sendv::pre_sendValue(QString qstr1)
{
    emit sendValue(qstr1);
}

uint16_t calc_cksm(void *pkt, int len) {
    uint16_t *buf = (uint16_t*)pkt;
    uint32_t cksm = 0;
    while (len > 1) {
        cksm += htons(*buf++);
        cksm = (cksm >> 16) + (cksm & 0xffff);
        len -= 2;
    } if (len) {
        cksm += *((uint8_t*)buf);
        cksm = (cksm >> 16) + (cksm & 0xffff);
    }
    return (uint16_t)((~cksm) & 0xffff);
}

//buf表示报文中需要计算校验和的各个数，n是数据个数

uint16_t calc_cksm_ip(uint16_t *buf, int n)
{
    uint32_t ssum;
    for(ssum = 0 ; n > 0; n--)
    {
        ssum += htons(*buf++);
    }
    ssum = (ssum >> 16) + (ssum & 0xFFFF);
    ssum += (ssum >> 16);
    return (uint16_t)(~ssum);
}

//uint16_t calc_cksm_ip(uint16_t* buffer, int size)
//{
//    unsigned long cksum = 0;
//    while(size>1)
//    {
//        cksum += *buffer++;
//        size -= sizeof(uint16_t);
//    }
//    if(size)
//    {
//        cksum += *(uchar*)buffer;
//    }
//    cksum = (cksum>>16) + (cksum&0xffff);
//    cksum += (cksum>>16);
//    return (uint16_t)(~cksum);
//}

void set_psdheader(struct psd_header* ph,struct iphdr *ip, uint16_t tl){
    ph->saddr=ip->saddr;
    ph->daddr=ip->daddr;
    ph->mbz=0;
    ph->ptcl=6;
    ph->tcpl=htons(tl);
}

unsigned char* getkey(int k){//扩展为256位密钥
    unsigned char * r;
    r=new unsigned char[32];
    int i;
    for(i=0;i<32;i++){
        r[i]=(unsigned char)k;
    }
    return r;
}

diffie_hellman DH1;//client-middle
diffie_hellman DH2;//middle-server
int flag=1;
void Cappackets::processPacket(u_char *arg, const struct pcap_pkthdr* pkthdr, const u_char * packet){

    unsigned char server_mac[]={0x00,0x0c,0x29,0xca,0x7d,0x23};
    unsigned char client_mac[]={0x00,0x0c,0x29,0xd4,0xaa,0x8c};
    unsigned char my_mac[]={0x00,0x0c,0x29,0x41,0x08,0x8a};//这个地方的三处要改

    struct ether_header *ethernet;
    struct iphdr *ip;
    struct tcphdr *tcp;

    char srcip_str[16];
    memset(srcip_str,0,16);
    ip_rule * ip_r=(ip_rule*)arg;

    ethernet = (struct ether_header*)(packet);  //ethernet header
    ip = (struct iphdr*)(packet + ETHER_HDR_LEN);   //ip head
    tcp = (struct tcphdr*)(packet + ETHER_HDR_LEN+ sizeof(struct iphdr));   //tcp head

    int hdr_len = ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct tcphdr) + 12;//报文头长度
    int dl = pkthdr->len - hdr_len;//数据报实际长度减去报文头长度，即报文中data的长度

    inet_ntop(AF_INET,&(ip->saddr),srcip_str,16);
    //src mac
    memcpy(ethernet->ether_shost,my_mac,6);//将源mac改为中间人mac

    int delt = 0;
    if(memcmp(srcip_str, ip_r->client_ip, strlen(srcip_str))==0)//client->server
    {//client

        sv.pre_sendValue("from client");
        int lengthA;//原报文长度
        int lengthB;//修改后报文长度

        lengthA = dl;

        uint16_t tcpcFLAG;

        tcpcFLAG = *(uint16_t*)(packet + 46);
        tcpcFLAG = tcpcFLAG & (uint16_t)0xff0f;
        if(tcpcFLAG == (uint16_t)0x1000 || dl < 9)
        {

            //计算IP校验和
            memset((uchar*)packet + 24, 0, 2);

            uint16_t det = calc_cksm_ip((uint16_t*)(packet + 14), 10);
            //*tmp_iph_ck = calc_cksm_ip((uint16_t*)packet + 14, 10);
            uint8_t high = det / 256;
            uint8_t low = det % 256;
            QByteArray c1,c2;
            c1.append((uchar)high);//高字节
            c2.append((uchar)low);//低字节
            char* d1, *d2;
            d1=c1.data();
            d2 = c2.data();

            memcpy((uchar*)packet + 24, d1, 1);
            memcpy((uchar*)packet + 25, d2, 1);

            memcpy(ethernet->ether_dhost,server_mac,6);//将目的mac改为服务器
            pcap_sendpacket(ip_r->p,packet,pkthdr->len + delt);//pkthdr->len不变
            return;
        }
        //提取消息部分，假定ack消息自动转发
        QByteArray tmpq;
        int i;
        for(i = 66 ;i < pkthdr->len ;i++)
        {
            tmpq.append(packet[i]);
        }
        QByteArray tmpq2=QByteArray::fromBase64(tmpq);//base64解码
        QString tmpstr = QString::fromUtf8(tmpq2);//utf-8解码，为了支持中文用户名
        //qDebug()<<"from client";
        //qDebug()<<tmpstr;


        //这个消息的头部有两种可能，request或者data
        //对于请求登录消息，需要修改KA，对于data消息，需要显示在界面上（先在debug上显示）

        QStringList list;
        list=tmpstr.split("-");//以"-"做分隔

        if(list.at(0)=="request")
        {//packet[hdr_len]="request-\`username\`-\`password\`-\r`c_rsa_e\`-\`c_rsa_n\`-\`g\`-\`p\`-\`Ya\`"，截到公钥报，修改公钥和校验码再发出
            QString username;
            QString passwordhash;
            QString rsa_e;
            QString rsa_n;
            QString g0;
            QString p0;
            QString KA0;

            if(list.count() < 7)
            {
                qDebug()<<"MITM error";
            }
            username=list.at(1);
            passwordhash=list.at(2);
            rsa_e=list.at(3);
            rsa_n=list.at(4);
            g0=list.at(5);
            p0=list.at(6);
            KA0=list.at(7);

            int g=g0.toInt();
            int p=p0.toInt();
            int KA=KA0.toInt();

            DH1.g=g;
            DH1.p=p;
            DH1.KA=KA;
            if(flag==1){
            DH1.server_get_key();//生成KM = DH1.KB = DH2.K1
            flag=0;
            }
            DH2.g=g;
            DH2.p=p;
            DH2.A=DH1.B;
            DH2.KA=DH1.KB;

            QString rslt_tmp=list.at(0)+"-"+list.at(1)+"-"+list.at(2)+"-"+list.at(3)+"-"+list.at(4)+"-"+list.at(5)+"-"+list.at(6)+"-"+QString::number(DH2.KA)+"-1-";

            QString s=rslt_tmp;
            int n=100;
            int c3=n-s.length();
            int i;
            s+="-";
            for(i=0;i<c3-1;i++){
                s+="1";
            }

            //KA->KM
            QByteArray rslt_bt=s.toUtf8().toBase64();

            lengthB=rslt_bt.size();//字节数
            char *rslt=rslt_bt.data();

           //修改数据内容
           memcpy((uchar*)(packet+hdr_len),rslt,lengthB);

           delt = lengthB - lengthA;
           //修改ip长度
           int iph_length;
           iph_length = lengthB + 66 - 14;
           QByteArray c;
           c.append((char)(iph_length / 256));//高字节
           c.append((char)(iph_length % 256));//低字节
           char* d;
           d = c.data();
           memcpy((uchar*)packet + 16, d, 2);

           //修改ip报文头校验和
           memset((uchar*)packet + 24, 0, 2);

           uint16_t det = calc_cksm_ip((uint16_t*)(packet + 14), 10);
           //*tmp_iph_ck = calc_cksm_ip((uint16_t*)packet + 14, 10);
           uint8_t high = det / 256;
           uint8_t low = det % 256;
           QByteArray c1,c2;
           c1.append((uchar)high);//高字节
           c2.append((uchar)low);//低字节
           char* d1, *d2;
           d1=c1.data();
           d2 = c2.data();

           memcpy((uchar*)packet + 24, d1, 1);
           memcpy((uchar*)packet + 25, d2, 1);


//           qDebug()<<"改IP校验和2";
//           qDebug()<<*tmp_iph_ck;
//           qDebug()<<(uchar)*tmp_iph_ck;
//           qDebug()<<"改IP校验和3";
//           memcpy((uchar*)packet, (uchar*)tmp_iph_ck, 2);


//           qDebug()<<"======recieve  from client ===============";
//           qDebug()<<"username:"<<username;
//           qDebug()<<"password hash:"<<passwordhash;
//           qDebug()<<"rsa_e:"<<rsa_e<<" rsa_n:"<<rsa_n;
//           qDebug()<<"g:"<<g;
//           qDebug()<<"p:"<<p;
//           qDebug()<<"KA:"<<KA;
//           qDebug()<<"KM:"<<DH1.KB;
//           qDebug()<<"前后字节差："<<lengthB-lengthA;
//           qDebug()<<"发送的字符串："<<rslt_tmp;
//           qDebug()<<"============================================";

            //recalculate the checksum
            uint16_t tcp_len = pkthdr->len - ETHER_HDR_LEN - sizeof(struct iphdr) +delt;
            unsigned char * data_for_checksum = (unsigned char*)malloc(tcp_len + sizeof(struct psd_header));
            struct psd_header ph;
            bzero(data_for_checksum, tcp_len + sizeof(ph));
            set_psdheader(&ph, ip, tcp_len);
            memcpy(data_for_checksum, (void*)(&ph), sizeof(ph));
            tcp->check = 0;
            memcpy(data_for_checksum+sizeof(ph), tcp, tcp_len);
            uint16_t cs= ntohs(calc_cksm(data_for_checksum, tcp_len + sizeof(ph)));
            tcp->check=cs;
        }
        else if(list.at(0)=="data")
        {
            //消息格式data-用户名-原消息长度-经过处理的密文（只进行了aesgcm加密),用DH1.K解密
             qDebug()<<"========recv client msg==========";
             QString username;
             int length;
             username=list.at(1);
             QString s;
             s=list.at(2);
             length=s.toInt();
//             qDebug()<<"username:"<<username;
//             qDebug()<<"length:"<<length;
             int readbuflenth=dl;//数据的长度

             //aes解密
             QString begin;//计算消息头的长度，AES密文的长度
             begin="data-"+username+"-"+list.at(2)+"-";
             QByteArray b;
             b=begin.toUtf8();
//             qDebug()<<"begin:"<<begin;
//             qDebug()<<"b length:"<<b.length();

             int beginlength=b.length();
             int aescipherlength;
             aescipherlength=tmpq2.length()-b.length();//aes密文长度
             QByteArray aescipherbytearray;
             int i;
             for(i=beginlength;i<beginlength+aescipherlength;i++){
                 aescipherbytearray.append(tmpq2[i]);
             }
//             qDebug()<<"readbuf length"<<readbuflenth;
//             qDebug()<<"aescipherlength"<<aescipherbytearray.length();
             aes_gcm aesg(aesg.getgcmchar(getkey(DH1.K),32));
             aesg.input2=aescipherbytearray;
             aesg.aes_decrypt();
             QString aesoutput;
             aesoutput=aesg.output2;
//             qDebug()<<"aes output"<<aesoutput;



             //解密后的数据提取原文，进行MD5和签名验证
             QString msg;
             msg=aesoutput.mid(0,length);
             QString uistring;//要显示的字符串
             uistring=username+":"+msg;
             qDebug()<<"显示："<<uistring;
             sv.pre_sendValue("");
             sv.pre_sendValue("FROM " + uistring);
             sv.pre_sendValue("");

             qDebug()<<"===========complete=============";
//             qDebug()<<"===========jiami=============";


             //解密需要重新加密，修改ip长度和校验和？？长度是否改变
             //长度不变就不需要
             aes_gcm aesg2(aesg2.getgcmchar(getkey(DH2.K),32));
             //消息头
             QString tmp;
             tmp="data-"+list.at(1)+"-"+list.at(2)+"-";

             QString s3=msg;
             int n=100;
             int c3=n-s3.length();
             s3+="-";
             for(i=0;i<c3-1;i++){
                 s3+="1";
             }

             //消息
             aesg2.input1=s3;
             aesg2.aes_encrypt();
             QByteArray aesoutput2=aesg2.output1;
             //拼接
             QByteArray rslt_bt1=tmp.toUtf8();
             QByteArray rslt_bt2=aesoutput2;
             QByteArray rslt_bt=rslt_bt1.append(rslt_bt2);
             rslt_bt=rslt_bt.toBase64();

             lengthA=dl;
             lengthB=rslt_bt.size();//字节数
             char *rslt=rslt_bt.data();
            //修改数据内容
            memcpy((uchar*)(packet+hdr_len),rslt,lengthB);

            delt=lengthB-lengthA;

            //ui->textEdit->append(uistring);
            //修改ip长度
            int iph_length;
            iph_length = lengthB + 66 - 14;
            QByteArray c;
            c.append((char)(iph_length / 256));//高字节
            c.append((char)(iph_length % 256));//低字节
            char* d;
            d = c.data();
            memcpy((uchar*)packet + 16, d, 2);

            //修改ip报文头校验和
            memset((uchar*)packet + 24, 0, 2);

            uint16_t det = calc_cksm_ip((uint16_t*)(packet + 14), 10);
            //*tmp_iph_ck = calc_cksm_ip((uint16_t*)packet + 14, 10);
            uint8_t high = det / 256;
            uint8_t low = det % 256;
            QByteArray c1,c2;
            c1.append((uchar)high);//高字节
            c2.append((uchar)low);//低字节
            char* d1, *d2;
            d1=c1.data();
            d2 = c2.data();

            memcpy((uchar*)packet + 24, d1, 1);
            memcpy((uchar*)packet + 25, d2, 1);

            //recalculate the checksum
            uint16_t tcp_len =pkthdr->len-ETHER_HDR_LEN-sizeof(struct iphdr) +delt;
            unsigned char * data_for_checksum=(unsigned char*)malloc(tcp_len+sizeof(struct psd_header));
            struct psd_header ph;
            bzero(data_for_checksum, tcp_len+sizeof(ph));
            set_psdheader(&ph, ip, tcp_len);
            memcpy(data_for_checksum, (void*)(&ph), sizeof(ph));
            tcp->check=0;
            memcpy(data_for_checksum+sizeof(ph), tcp, tcp_len);
            uint16_t cs=ntohs(calc_cksm(data_for_checksum, tcp_len+sizeof(ph)));
            tcp->check=cs;
        }
        memcpy(ethernet->ether_dhost,server_mac,6);//将目的mac改为服务器
    }
    else if(memcmp(srcip_str, ip_r->server_ip, strlen(srcip_str))==0)
    {//server->client
        sv.pre_sendValue("from server");
        int lengthA;//原报文长度
        int lengthB;//修改后报文长度

        lengthA=dl;

        uint16_t tcpcFLAG;
        tcpcFLAG = *(uint16_t*)(packet + 46);
        tcpcFLAG = tcpcFLAG & (uint16_t)0xff0f;
        if(tcpcFLAG == (uint16_t)0x1000 || dl < 9)
        {
            memcpy(ethernet->ether_dhost,client_mac,6);//将目的mac改为服务器
            pcap_sendpacket(ip_r->p,packet,pkthdr->len + delt);//pkthdr->len不变
            return;
        }

        //提取消息部分，假定ack消息自动转发
        QByteArray tmpq;
        int i;
        for(i = 66 ;i < pkthdr->len ;i++)
        {
            tmpq.append(packet[i]);
        }
        QByteArray tmpq2=QByteArray::fromBase64(tmpq);//base64解码
        QString tmpstr = QString::fromUtf8(tmpq2);//utf-8解码，为了支持中文用户名
//        qDebug()<<tmpstr;


        //这个消息的头部有三种可能，或者ok，data，error,先只考虑前两种
        //对于允许登录消息&用户列表信息：ok-服务器rsa公钥e-n-KB-当前人数-用户名1-用户名2....，需要修改KB为KM
        //对于data消息，需要显示在界面上（先在debug上显示）

        QStringList list;
        list=tmpstr.split("-");//以"-"做分隔

        //server
        if(list.at(0)=="ok")
        {//允许登录消息

            QString rsa_e;
            QString rsa_n;
            QString KB0;

            rsa_e=list.at(1);
            rsa_n=list.at(2);
            KB0=list.at(3);

            int KB=KB0.toInt();

            DH2.KB=KB;
            DH2.client_get_key();//生成K2,已知K1,K2,将DH1.KB（KM）代替KB传回去

            QString rslt_tmp;//KB->KM
            int i;
            for(i=0;i<list.count();i++){
               if(i==3){
                    rslt_tmp+=QString::number(DH1.KB)+"-";
               }else{
                   rslt_tmp+=list.at(i)+"-";
               }
            }
            QString s=rslt_tmp;
            int n=100;
            int c3=n-s.length();
            s+="-";
            for(i=0;i<c3-1;i++){
                s+="1";
            }
            QByteArray rslt_bt=s.toUtf8().toBase64();

            lengthB=rslt_bt.size();//字节数
            char *rslt=rslt_bt.data();

            //修改数据内容
            memcpy((uchar*)(packet+hdr_len),rslt,lengthB);

            delt = lengthB - lengthA;

            //修改长度
            int iph_length;
            iph_length = lengthB + 66 - 14;
            QByteArray c;
            c.append((char)(iph_length / 256));//高字节
            c.append((char)(iph_length % 256));//低字节
            char* d;
            d = c.data();
            memcpy((uchar*)packet + 16, d, 2);

            //修改ip报文头校验和
            memset((uchar*)packet + 24, 0, 2);

            uint16_t det = calc_cksm_ip((uint16_t*)(packet + 14), 10);
            //*tmp_iph_ck = calc_cksm_ip((uint16_t*)packet + 14, 10);
            uint8_t high = det / 256;
            uint8_t low = det % 256;
            QByteArray c1,c2;
            c1.append((uchar)high);//高字节
            c2.append((uchar)low);//低字节
            char* d1, *d2;
            d1=c1.data();
            d2 = c2.data();

            memcpy((uchar*)packet + 24, d1, 1);
            memcpy((uchar*)packet + 25, d2, 1);


//           qDebug()<<"======recieve  from server ===============";
//           qDebug()<<"rsa_e:"<<rsa_e<<" rsa_n:"<<rsa_n;
//           qDebug()<<"KB:"<<KB;
//           qDebug()<<"K1:"<<DH1.K;
//           qDebug()<<"K2:"<<DH2.K;
//           qDebug()<<"前后字节差："<<lengthB-lengthA;
//           qDebug()<<"发送的字符串："<<rslt_tmp;
//           qDebug()<<"============================================";

            //recalculate the checksum
            uint16_t tcp_len = pkthdr->len - ETHER_HDR_LEN - sizeof(struct iphdr) +delt;
            unsigned char * data_for_checksum=(unsigned char*)malloc(tcp_len+sizeof(struct psd_header));
            struct psd_header ph;
            bzero(data_for_checksum, tcp_len+sizeof(ph));
            set_psdheader(&ph, ip, tcp_len);
            memcpy(data_for_checksum, (void*)(&ph), sizeof(ph));
            tcp->check=0;
            memcpy(data_for_checksum+sizeof(ph), tcp, tcp_len);
            unsigned short cs=ntohs(calc_cksm(data_for_checksum, tcp_len+sizeof(ph)));
            tcp->check=cs;
        }
        else if(list.at(0)=="data")
        {//建议改协议前缀data
            //decrypt
//            char *buff=(char*)packet+hdr_len;
//            char *plain=(char*)malloc(长度);
//            bzero(plain, sizeof(buff));

            //消息格式data-用户名-原消息长度-经过处理的密文（只进行了aesgcm加密),用DH2.K解密
             qDebug()<<"========recv server echo msg==========";
             QString username;
             int length;
             username=list.at(1);
             QString s;
             s=list.at(2);
             length=s.toInt();
//             qDebug()<<"username:"<<username;
//             qDebug()<<"length:"<<length;
             int readbuflenth=dl;//数据的长度

             //aes解密
             QString begin;//计算消息头的长度，AES密文的长度
             begin="data-"+username+"-"+list.at(2)+"-";
             QByteArray b;
             b=begin.toUtf8();
//             qDebug()<<"begin:"<<begin;
//             qDebug()<<"b length:"<<b.length();

             int beginlength=b.length();
             int aescipherlength;
             aescipherlength=tmpq2.length()-b.length();//aes密文长度
             QByteArray aescipherbytearray;
             int i;
             for(i=beginlength;i<beginlength+aescipherlength;i++){
                 aescipherbytearray.append(tmpq2[i]);
             }
//             qDebug()<<"readbuf length"<<readbuflenth;
//             qDebug()<<"aescipherlength"<<aescipherbytearray.length();
             aes_gcm aesg(aesg.getgcmchar(getkey(DH2.K),32));
             aesg.input2=aescipherbytearray;
             aesg.aes_decrypt();
             QString aesoutput;
             aesoutput=aesg.output2;
//             qDebug()<<"aes output"<<aesoutput;


             //解密后的数据提取原文，进行MD5和签名验证
             QString msg;
             msg=aesoutput.mid(0,length);
             QString uistring;//要显示的字符串
             uistring=username+":"+msg;
             qDebug()<<"显示："<<uistring;

             sv.pre_sendValue("");
             sv.pre_sendValue("FROM " + uistring);
             sv.pre_sendValue("");
             qDebug()<<"===========complete=============";


             //解密需要重新加密，修改ip长度和校验和？？长度是否改变
             //长度不变就不需要
             aes_gcm aesg2(aesg2.getgcmchar(getkey(DH1.K),32));
             //消息头
             QString tmp;
             tmp="data-"+list.at(1)+"-"+list.at(2)+"-";
             QString s3=msg;
             int n=100;
             int c3=n-s3.length();
             s3+="-";
             for(i=0;i<c3-1;i++){
                 s3+="1";
             }
             //消息
             aesg2.input1=s3;
             aesg2.aes_encrypt();
             QByteArray aesoutput2=aesg2.output1;
             //拼接
             QByteArray rslt_bt1=tmp.toUtf8();
             QByteArray rslt_bt2=aesoutput2;
             QByteArray rslt_bt=rslt_bt1.append(rslt_bt2);
             rslt_bt=rslt_bt.toBase64();

             lengthA=dl;
             lengthB=rslt_bt.size();//字节数
             char *rslt=rslt_bt.data();
            //修改数据内容
            memcpy((uchar*)(packet+hdr_len),rslt,lengthB);

            delt=lengthB-lengthA;
//            qDebug()<<"delt:"<<delt;
            //ui->textEdit->append(uistring);
            //修改ip长度
            int iph_length;
            iph_length = lengthB + 66 - 14;
            QByteArray c;
            c.append((char)(iph_length / 256));//高字节
            c.append((char)(iph_length % 256));//低字节
            char* d;
            d = c.data();
            memcpy((uchar*)packet + 16, d, 2);

            //修改ip报文头校验和
            memset((uchar*)packet + 24, 0, 2);

            uint16_t det = calc_cksm_ip((uint16_t*)(packet + 14), 10);
            //*tmp_iph_ck = calc_cksm_ip((uint16_t*)packet + 14, 10);
            uint8_t high = det / 256;
            uint8_t low = det % 256;

            QByteArray c1,c2;
            c1.append((uchar)high);//高字节
            c2.append((uchar)low);//低字节
            char* d1, *d2;
            d1=c1.data();
            d2 = c2.data();

            memcpy((uchar*)packet + 24, d1, 1);
            memcpy((uchar*)packet + 25, d2, 1);

            //recalculate the checksum
            uint16_t tcp_len =pkthdr->len-ETHER_HDR_LEN-sizeof(struct iphdr) +delt;
            unsigned char * data_for_checksum=(unsigned char*)malloc(tcp_len+sizeof(struct psd_header));
            struct psd_header ph;
            bzero(data_for_checksum, tcp_len+sizeof(ph));
            set_psdheader(&ph, ip, tcp_len);
            memcpy(data_for_checksum, (void*)(&ph), sizeof(ph));
            tcp->check=0;
            memcpy(data_for_checksum+sizeof(ph), tcp, tcp_len);
            uint16_t cs=ntohs(calc_cksm(data_for_checksum, tcp_len+sizeof(ph)));
            tcp->check=cs;
        }
        memcpy(ethernet->ether_dhost,client_mac,6);
    }
    pcap_sendpacket(ip_r->p,packet,pkthdr->len + delt);//pkthdr->len不变
    return;
}

void middlewindow::getValue(QString qstr)
{
    ui->textEdit->append(qstr);
}

void middlewindow::on_pushButton_clicked()//开始
{
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(true);

    char* ch[5];
    ch[0] = "";

    QObject::connect(&sv,SIGNAL(sendValue(QString)),this,SLOT(getValue(QString)));//这句放在调用处

    QString str = ui->lineEdit->text();//客户端IP
    QByteArray tmp = str.toLatin1();
    ch[1]=tmp.data();

    str = ui->lineEdit_2->text();//服务器IP
    tmp = str.toLatin1();
    ch[2]=tmp.data();

    str = ui->lineEdit_3->text();//客户端mac
    tmp = str.toLatin1();
    ch[3]=tmp.data();

    str = ui->lineEdit_4->text();//服务器mac
    tmp = str.toLatin1();
    ch[4]=tmp.data();

    cp.start();

}

void middlewindow::on_pushButton_2_clicked()//停止
{
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);

    cp.stop();
    this->close();
}


int Cappackets::cap_start(char *addr[]){

    flag = 1;
    char errbuf[PCAP_ERRBUF_SIZE];
    char *device;
    memset(errbuf,0,PCAP_ERRBUF_SIZE);
    struct bpf_program filter;  //过滤器数据结构

    if ( (device = pcap_lookupdev(errbuf)) == NULL){
       fprintf(stderr, "ERROR: %s\n", errbuf);
       exit(1);
    }
    fprintf(stderr ,"Opening device %s\n", device);
    //打开设备eth0
    if ( (descr = pcap_open_live(device, 2048, 1, 500, errbuf)) == NULL){
        fprintf(stderr, "ERROR: %s\n", errbuf);
        exit(1);
    }
    //编写过滤规则
    memset(rule,0,128);
    strncat(rule,"(src host ",10);
    strncat(rule,addr[1],strlen(addr[1]));
    strncat(rule," and dst host ",14);
    strncat(rule,addr[2],strlen(addr[2]));
    strncat(rule,") or (src host ",15);
    strncat(rule,addr[2],strlen(addr[2]));
    strncat(rule," and dst host ",14);
    strncat(rule,addr[1],strlen(addr[1]));
    strncat(rule, ")", 1);

    if(pcap_compile(descr,&filter,rule,1,0)<0){//编译过滤规则
        printf("error1\n");
        return 0;
    }
    if(pcap_setfilter(descr,&filter)<0){//应用过滤规则
        printf("error2\n");
        return 0;
    }
    ip_rule ip_r;
    ip_r.p=descr;

    uchar *addr_cli = (uchar*) "192.168.233.134";
    uchar *addr_ser = (uchar*) "192.168.233.135";

    memset(ip_r.client_ip,0,15);
    memcpy(ip_r.client_ip, addr_cli,strlen((char*)addr_cli));
    memset(ip_r.server_ip,0,15);
    memcpy(ip_r.server_ip, addr_ser,strlen((char*)addr_ser));

    //调用pcap库pcap_loop函数，pcap_loop函数回调数据包处理函数processPacket

    if (pcap_loop(descr, -1, Cappackets::processPacket, (u_char *)&ip_r) == -1){
        fprintf(stderr, "ERROR: %s\n", pcap_geterr(descr) );
        exit(1);
    }
    return 0;
}
